﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace N2.BlogEngine.Providers
{
	using BlogEngine;
	using Items;
	using N2;
	using N2.Details;
	using be = global::BlogEngine.Core;
	using n2 = N2.BlogEngine;
	
	partial class N2BlogProvider
	{
		public override be.Post SelectPost(Guid id)
		{
			var _post = Context.Current.Persister.Get<BePost>(id.ToInt());
			
			if (null == _post && this.UseFallBackProvider) {
				be.Post _innerPost = FallBackProvider.SelectPost(id);
				_innerPost.Id = id;
				this.UpdatePost(_innerPost);

				return _innerPost;
			} else {
				
				be.Post _bePost = _post.AsBlogEngine();

				//Tags
				_bePost.Tags.AddRange(_post.Tags);
				_bePost.Tags.MarkOld();

				//Categories
				_bePost.Categories.AddRange(_post.Categories
						.Select<BeCategory, be.Category>(ItemExtensions.AsBlogEngine));

				//Comments
				_bePost.Comments.AddRange(
					_post.GetChildren()
						.OfType<BeComment>()
						.Select(_comment => _comment.AsBlogEngine(_bePost)));
				_bePost.Comments.Sort();

				//Email notifications
				_bePost.NotificationEmails.AddRange(
					_post.NotificationEmails.ToArray());

				return _bePost;
			}
		}

		public override void InsertPost(be.Post post)
		{
			this.UpdatePost(post);
		}

		public override void UpdatePost(be.Post post)
		{
			BePost _post = post.AsN2();

			_post.Tags.Clear();
			post.Tags.ForEach(_post.Tags.Add);

			_post.Categories.Clear();
			//first, ensure entities exist
			post.Categories.ForEach(this.UpdateCategory);
			//next, store links to entities
			post.Categories
				.ConvertAll<BeCategory>(ItemExtensions.AsN2)
				.ForEach(_post.Categories.Add);

			post.Comments.ForEach(_comment => {
				var _n2comment = Context.Persister.Get<BeComment>(_comment.Id.ToInt())
					?? Context.Definitions.CreateInstance<BeComment>(_post);
				
				Context.Persister.Save(_comment.AsN2(_n2comment));
			});

			_post.NotificationEmails.Clear();
			post.NotificationEmails
				.Cast<string>()
				.ToList()
				.ForEach(_post.NotificationEmails.Add);
			
			Context.Persister.Save(_post);
		}

		public override void DeletePost(be.Post post)
		{
			Context.Persister.Delete(post.AsN2());
		}

		List<be.Post> TryFillingPosts()
		{
			return
				n2.BlogService
					.CurrentBlog
					.Posts
					.Items
					.ToList()
					.ConvertAll<be.Post>(ItemExtensions.AsBlogEngine);
		}

		public override List<be.Post> FillPosts()
		{
			var _posts = this.TryFillingPosts();

			if (!_posts.Any() && this.UseFallBackProvider) {
				FallBackProvider.FillPosts();
				_posts = this.TryFillingPosts();
			}

			return this.TryFillingPosts();
		}
	}
}
